package com.crk.javaTools;

import com.aspose.cells.Workbook;
import com.aspose.words.Document;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.text.PDFTextStripper;
import org.omg.CORBA.PUBLIC_MEMBER;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * Description:
 * PDF工具类
 * PDF转图片、PDF和word互转、PDF和excel互转
 * @author: chengrongkai
 * Date: 2020-07-09
 * Time: 10:46
 */
public class PdfTools {

    /**
     * pdf转成图片
     * @param filePath 文件路径
     * @param outPath 输出路径
     * @param multiple 是否转成多张图片(每一页生成一张图片)
     */
    public static void pdfToImage(String filePath,String outPath,boolean multiple){
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            inputStream = new FileInputStream(filePath);
            outPath = checkFilePathExist(filePath,outPath,multiple);
            outputStream = new FileOutputStream(outPath);
            pdfToImage(inputStream,outputStream,multiple);
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try {
                if (null != inputStream){
                    inputStream.close();
                }
                if (null != outputStream){
                    outputStream.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }



    /**
     * pdf转成图片
     * @param inputStream 输入文件流
     * @param outPath 输出路径
     * @param multiple 是否转成多张图片(每一页生成一张图片)
     */
    public static void pdfToImage(InputStream inputStream,String outPath,boolean multiple){
        OutputStream outputStream = null;
        try {
            outPath = checkFilePathExist(null,outPath,multiple);
            outputStream = new FileOutputStream(outPath);
            pdfToImage(inputStream,outputStream,multiple);
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try{
                if (null != outputStream){
                    outputStream.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }



    /**
     * pdf转成图片
     * @param filePath 文件路径
     * @param outputStream 输出流
     * @param multiple 是否转成多张图片(每一页生成一张图片)
     */
    public static void pdfToImage(String filePath,OutputStream outputStream,boolean multiple){
        InputStream inputStream = null;
        try {
            checkFilePathExist(filePath,null,multiple);
            inputStream = new FileInputStream(filePath);
            pdfToImage(inputStream,outputStream,multiple);
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try{
                if (null != inputStream){
                    inputStream.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }

        }
    }


    /**
     * pdf转成图片
     * @param inputStream 输入文件流
     * @param outputStream 输出流
     * @param multiple 是否转成多张图片(每一页生成一张图片)
     */
    public static void pdfToImage(InputStream inputStream,OutputStream outputStream,boolean multiple)throws IOException{
        if (multiple){
            pdfToImageMultiple(inputStream, outputStream);
        }else{
            pdfToImageSingle(inputStream, outputStream);
        }
    }

    private static String checkFilePathExist(String filePath,String outPath,boolean multiple)throws IOException{
        String fileName = "转换后";
        if (null != filePath){
            File file = new File(filePath);
            if (!file.exists()){
                throw new FileNotFoundException(filePath+"文件不存在");
            }
            fileName = file.getName();
        }
        if (null != outPath){
            File file = new File(outPath);
            if (!file.exists()){
                file.mkdir();
            }

            if (multiple){
                fileName = fileName.substring(0,fileName.lastIndexOf(".")+1)+"zip";
            }
            outPath = outPath+File.separator+fileName;
        }
        return outPath;

    }

    private static void pdfToImageSingle(InputStream inputStream,OutputStream outputStream){
        PDDocument pdf = null;
        BufferedImage  image = null;
        try {
            pdf = PDDocument.load(inputStream);
            int actSize  = pdf.getNumberOfPages();
            List<BufferedImage> piclist = new ArrayList<BufferedImage>();
            for (int i = 0; i < actSize; i++) {
                image = new PDFRenderer(pdf).renderImageWithDPI(i,130, ImageType.RGB);
                piclist.add(image);
            }
            yPic(piclist,outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if (null != pdf){
                    pdf.close();
                }
                if (null != inputStream){
                    inputStream.close();
                }
                image = null;
                if (null != outputStream){
                    outputStream.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }

    /**
     * pdf转成图片:转成多张图片,保存成zip输出
     * @param inputStream
     * @param outputStream
     */
    private static void pdfToImageMultiple(InputStream inputStream,OutputStream outputStream){
        ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
        PDDocument doc = null;
        PDFRenderer renderer = null;
        BufferedImage image = null;
        FileInputStream in = null;
        try {
            doc = PDDocument.load(inputStream);
            renderer = new PDFRenderer(doc);
            int pageCount = doc.getNumberOfPages();
            File[] files =new File[pageCount];
            for(int i=0; i<pageCount; i++){
                // 方式1,第二个参数是设置缩放比(即像素)
                // BufferedImage image = renderer.renderImageWithDPI(i, 296);
                // 方式2,第二个参数是设置缩放比(即像素)
                //第二个参数越大生成图片分辨率越高，转换时间也就越长
                image = renderer.renderImage(i, 1.25f);
                String fileName = "页"+i + ".jpg";
                files[i] = new File(fileName);
                zipOutputStream.putNextEntry(new ZipEntry(fileName));
                ImageIO.write(image, "PNG", zipOutputStream);
            }
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try {
                zipOutputStream.closeEntry();
                zipOutputStream.close();
                doc.close();
                renderer = null;
                image = null;
                if (null != in){
                    in.close();
                }
                if (null != outputStream){
                    outputStream.close();
                }

            }catch (IOException e){
                e.printStackTrace();
            }

        }

    }


    /**
     * 将宽度相同的图片，竖向追加在一起 ##注意：宽度必须相同
     * @param picList  文件流数组
     * @param outputStream 输出流（可传递，传递时采用流的方式写入）
     */
    private static void yPic(List<BufferedImage> picList, OutputStream outputStream){// 纵向处理图片
        if (picList == null || picList.size() <= 0) {
            System.out.println("图片数组为空!");
            return;
        }
        try {
            // 总高度
            int height = 0;
            // 总宽度
            int width = 0;
            // 临时的高度 , 或保存偏移高度
            int _height = 0;
            // 临时的高度，主要保存每个高度
            int __height = 0;
            // 图片的数量
            int picNum = picList.size();
            // 保存每个文件的高度
            int[] heightArray = new int[picNum];
            // 保存图片流
            BufferedImage buffer = null;
            // 保存所有的图片的RGB
            List<int[]> imgRGB = new ArrayList<int[]>();
            // 保存一张图片中的RGB数据
            int[] _imgRGB;
            for (int i = 0; i < picNum; i++) {
                buffer = picList.get(i);
                heightArray[i] = _height = buffer.getHeight();// 图片高度
                if (i == 0) {
                    width = buffer.getWidth();// 图片宽度
                }
                // 获取总高度
                height += _height;
                // 从图片中读取RGB
                _imgRGB = new int[width * _height];
                _imgRGB = buffer.getRGB(0, 0, width, _height, _imgRGB, 0, width);
                imgRGB.add(_imgRGB);
            }
            // 设置偏移高度为0
            _height = 0;
            // 生成新图片
            BufferedImage imageResult = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            for (int i = 0; i < picNum; i++) {
                __height = heightArray[i];
                // 计算偏移高度
                if (i != 0) _height += __height;
                // 写入流中
                imageResult.setRGB(0, _height, width, __height, imgRGB.get(i), 0, width);
            }

            ImageIO.write(imageResult, "jpg", outputStream);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * pdf转word
     * @param inputStream 输入
     * @param outputStream 输出
     */
    public static void pdfToWord(InputStream inputStream,OutputStream outputStream){
        PDDocument doc = null;
        Writer writer = null;
        PDFTextStripper stripper = null;
        try {
            doc = PDDocument.load(inputStream);
            writer = new OutputStreamWriter(outputStream, "UTF-8");
            stripper = new PDFTextStripper();
            int pageNumber = doc.getNumberOfPages();
            stripper.setSortByPosition(true);
            stripper.setStartPage(1);
            stripper.setEndPage(pageNumber);
            stripper.writeText(doc, writer);

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if (null != writer){
                    writer.close();
                }
                if (null != doc){
                    doc.close();
                }
                if (null != inputStream){
                    inputStream.close();
                }
                if (null != outputStream){
                    outputStream.close();
                }

            }catch (Exception e){
                e.printStackTrace();
            }

        }
    }
    /**
     * pdf转word
     * @param inputPath 输入
     * @param outputStream 输出
     */
    public static void pdfToWord(String inputPath,OutputStream outputStream){
        InputStream inputStream = null;
        try {
            checkFilePathExist(inputPath,null,false);
            inputStream = new FileInputStream(inputPath);
            pdfToWord(inputStream, outputStream);
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try{
                if (null != inputStream){
                    inputStream.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }

        }
    }
    /**
     * pdf转word
     * @param inputStream 输入
     * @param outPath 输出
     */
    public static void pdfToWord(InputStream inputStream,String outPath){
        OutputStream outputStream = null;
        try {
            checkFilePathExist(null,outPath,false);
            outputStream = new FileOutputStream(outPath);
            pdfToWord(inputStream, outputStream);
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try{
                if (null != outputStream){
                    outputStream.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }

        }
    }
    /**
     * pdf转word
     * @param inputPath 输入
     * @param outPath 输出
     */
    public static void pdfToWord(String inputPath,String outPath){
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            checkFilePathExist(inputPath,outPath,false);
            inputStream = new FileInputStream(inputPath);
            outputStream = new FileOutputStream(outPath);
            pdfToWord(inputStream, outputStream);
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try{
                if (null != outputStream){
                    outputStream.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }

        }
    }



    /**
     * 读取证书
     * @return
     */
    private static boolean getLicense() {
        boolean result = false;
        try {

            InputStream is = PdfTools.class.getClassLoader().getResourceAsStream("license.xml"); // license.xml应放在..\WebRoot\WEB-INF\classes路径下
            License aposeLic = new License();
            aposeLic.setLicense(is);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


    public static void pdf2doc(String wordPath, String pdfPath){
        if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
            return;
        }
        try {
            long old = System.currentTimeMillis();
            File file = new File(pdfPath); //新建一个pdf文档
            FileOutputStream os = new FileOutputStream(file);
            Document doc = new Document(wordPath); //Address是将要被转化的word文档
            doc.save(os, SaveFormat.DOC);//全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
            long now = System.currentTimeMillis();
            os.close();
            System.out.println("共耗时：" + ((now - old) / 1000.0) + "秒"); //转化用时
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * WORD转PDF
     * @param wordPath 需要被转换的word全路径带文件名
     * @param pdfPath 转换之后pdf的全路径带文件名
     */
    public static void doc2pdf(String wordPath, String pdfPath) {
        if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
            return;
        }
        try {
            long old = System.currentTimeMillis();
            File file = new File(pdfPath); //新建一个pdf文档
            FileOutputStream os = new FileOutputStream(file);
            Document doc = new Document(wordPath); //Address是将要被转化的word文档
            doc.save(os, com.aspose.words.SaveFormat.PDF);//全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
            long now = System.currentTimeMillis();
            os.close();
            System.out.println("共耗时：" + ((now - old) / 1000.0) + "秒"); //转化用时
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * word转PDF
     * @param wordPath word文档
     * @param os 输出流
     */
    public static void doc2pdf(String wordPath, OutputStream os) {
        if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
            return;
        }
        try {
            long old = System.currentTimeMillis();
            Document doc = new Document(wordPath); //Address是将要被转化的word文档
            doc.save(os, com.aspose.words.SaveFormat.PDF);//全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
            long now = System.currentTimeMillis();
            os.close();
            System.out.println("共耗时：" + ((now - old) / 1000.0) + "秒"); //转化用时
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    /**
     * excel转PDF
     * @param excelPath 需要被转换的excel全路径带文件名
     * @param pdfPath 转换之后pdf的全路径带文件名
     */
    public static void excel2pdf(String excelPath, String pdfPath) {
        if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
            return;
        }
        try {
            long old = System.currentTimeMillis();
            Workbook wb = new Workbook(excelPath);// 原始excel路径
            FileOutputStream fileOS = new FileOutputStream(new File(pdfPath));
            wb.save(fileOS, com.aspose.cells.SaveFormat.PDF);
            fileOS.close();
            long now = System.currentTimeMillis();
            System.out.println("共耗时：" + ((now - old) / 1000.0) + "秒"); //转化用时
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * excel转PDF
     * @param excelPath 需要被转换的excel全路径带文件名
     * @param outputStream 输出流
     */
    public static void excel2pdf(String excelPath, OutputStream outputStream) {
        if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
            return;
        }
        try {
            long old = System.currentTimeMillis();
            Workbook wb = new Workbook(excelPath);// 原始excel路径
            wb.save(outputStream, com.aspose.cells.SaveFormat.PDF);
            outputStream.close();
            long now = System.currentTimeMillis();
            System.out.println("共耗时：" + ((now - old) / 1000.0) + "秒"); //转化用时
        } catch (Exception e) {
            e.printStackTrace();
        }
    }




    public static void main(String[] args) {
        String doc2pdf = "D:\\test1.doc";
        String pdfPath = "D:\\test1.pdf";
        pdf2doc(pdfPath,doc2pdf);
    }

}
